﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
using umbraco;
using umbraco.cms;
using umbraco.BusinessLogic;
using umbraco.presentation.masterpages;
using umbraco.uicontrols;
using System.IO;
using System.Diagnostics;

namespace AttackMonkey.TabHider
{
	public class ApplicationBase : umbraco.BusinessLogic.ApplicationBase
	{
		public ApplicationBase()
		{
			//attach event to page load
			umbracoPage.Load += new MasterPageLoadHandler(umbracoPage_Load);
			
			//set file system watcher on config file to refresh config without requiring app restart
			//var configPath = GlobalSettings.Path + "/../config/";
			var configPath = HttpContext.Current.Server.MapPath("~/config/");

			HttpContext.Current.Application.Add("tabHider", new FileSystemWatcher(configPath));
			var configFsw = (FileSystemWatcher)HttpContext.Current.Application["tabHider"];
			configFsw.EnableRaisingEvents = true;
			configFsw.IncludeSubdirectories = true;

			configFsw.Changed += new FileSystemEventHandler(expireConfig);
			configFsw.Created += new FileSystemEventHandler(expireConfig);
			configFsw.Deleted += new FileSystemEventHandler(expireConfig);
		}
		
		//expire the config and reset th instance
		protected void expireConfig(object sender, FileSystemEventArgs e)
		{
			Config.RefreshInstance();
		}

		//page load event for the main tab hider
		void umbracoPage_Load(object sender, EventArgs e)
		{
			//get path and make sure that it's the edit content page
			umbracoPage up = (umbracoPage)sender;
			string path = up.Page.Request.Path.ToLower().Replace((umbraco.GlobalSettings.Path.Replace("~","") + "/").ToLower(), "");
			
			if (path == "editcontent.aspx")
			{
				//only call this code if the current user is not the administrator, as they can see everything
				if (umbraco.helper.GetCurrentUmbracoUser().IsAdmin() == false || (umbraco.helper.GetCurrentUmbracoUser().IsAdmin() == true && umbraco.helper.GetCurrentUmbracoUser().Id > 0 && Config.Instance.OnlyShowToRoot == true))
				{
					string userType = umbraco.helper.GetCurrentUmbracoUser().UserType.Alias.ToLower();

					//get the tab view for the page
					ContentPlaceHolder cph = (ContentPlaceHolder)up.FindControl("body");
					Control c2 = cph.FindControl("TabView1");
					
					if (c2 != null)
					{
						TabView panel = (TabView)c2;
						
						//get a reference to the document so we can check it's type and tabs (this is a horrible hack)
						umbraco.cms.businesslogic.web.Document _document = new umbraco.cms.businesslogic.web.Document(int.Parse(HttpContext.Current.Request.QueryString["id"]));
						
						StringBuilder builder = new StringBuilder();
						
						string firstTab = string.Empty;
						
						for (int x = 0; x < _document.ContentType.getVirtualTabs.Length; x++)
						{
							string caption = _document.ContentType.getVirtualTabs[x].Caption.ToLower();
							
							bool hidden = false;
							
							if (Config.Instance.ConfigEntries.ContainsKey(caption))
							{
								foreach (ConfigItem ci in Config.Instance.ConfigEntries[caption])
								{
									//if the tab is for every page, or the doc type alias is found
									if (!ci.DocTypeAliases.Any() || ci.DocTypeAliases.Contains(_document.ContentType.Alias.ToLower()))
									{
										//if they're on the hide list, hide the tab and panel
										if (ci.HideFrom.Contains(userType))
										{
											//old code, replaced with client side hide, due to server siode not working with true/false and pickers
											//((TabPage)panel.GetPanels()[x]).Visible = false;
											
											//new code, only disables the validators if they said yes in config
											if (Config.Instance.DisableHiddenValidators == true)
											{
												List<BaseValidator> list = new List<BaseValidator>();

												FindControl(((TabPage)panel.GetPanels()[x]).Controls, list);

												foreach (BaseValidator val in list)
												{
													val.Enabled = false;
												}
											}
											
											builder.Append("$('#" + c2.ClientID + "_tab0" + (x + 1).ToString() + "').hide();\n");
											
											hidden = true;
											
											//additional code to handle first tab being hidden
											//if (x == 0)
											//{
												//builder.Append("$('#" + c2.ClientID + "_tab01layer').hide();\n");
												//builder.Append("$('#" + c2.ClientID + "_tab02layer').show();\n");
												//builder.Append("setActiveTab('" + c2.ClientID + "','" + c2.ClientID + "_tab02'," + c2.ClientID + "_tabs);\n");
											//}
										}
									}
								}
							}

							//if not already set, activate the first tab
							if (hidden == false)
							{
								if (string.IsNullOrEmpty(firstTab))
								{
									firstTab = "setActiveTab('" + c2.ClientID + "','" + c2.ClientID + "_tab0" + (x + 1).ToString() + "'," + c2.ClientID + "_tabs);\n";
								}
							}
						}
						
						builder.Append(firstTab);

						if (builder.Length > 0)
						{
							umbracoPage page = (umbracoPage)sender;
							page.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "attackmonkeyTabHider", "$(document).ready(function() { " + builder.ToString() + ";});", true);
						}
					}
				}
			}
		}

		//finds a list of basevalidator controls
		private static void FindControl(System.Web.UI.ControlCollection Controls, List<BaseValidator> list)
		{
			if (Controls != null && Controls.Count > 0)
			{
				for (int i = 0; i < Controls.Count; i++)
				{
					if (Controls[i] is BaseValidator)
					{
						BaseValidator found = Controls[i] as BaseValidator;
						list.Add(found);
						//break;
					}
					else
						FindControl(Controls[i].Controls, list);
				}
			}
		}
	}
}